﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace SpectrEngine.Framework.Collections
{
    internal sealed class DrawableComparer
        : IComparer<IDrawableItem>
    {
        public int Compare(IDrawableItem x, IDrawableItem y)
        {
            return x.DrawOrder.CompareTo(y.DrawOrder);
        }
    }

    public sealed class DrawList
        : List<IDrawableItem>
    {
        private DrawableComparer comparer;

        private bool dirtyFlag;

        public DrawList()
        {
            comparer = new DrawableComparer();
            dirtyFlag = false;
        }

        public void Register(DrawableGameNode node)
        {
            node.DrawOrderChanged += new EventHandler(node_DrawOrderChanged);
            node.Disposed += new EventHandler(node_Disposed);
            node.EnabledChanged += new EventHandler(node_EnabledChanged);

            this.Add(node);

            this.dirtyFlag = true;
        }

        void node_DrawOrderChanged(object sender, EventArgs e)
        {
            this.dirtyFlag = true;
        }

        void node_EnabledChanged(object sender, EventArgs e)
        {
            if (((IDrawableItem)sender).Visible)
            {
                this.Add((IDrawableItem)sender);
                this.dirtyFlag = true;
            }
            else
            {
                this.Remove((IDrawableItem)sender);
            }
        }
        
        void node_Disposed(object sender, EventArgs e)
        {
            this.Remove((IDrawableItem)sender);
        }

        public void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            if (dirtyFlag)
            {
                IDrawableItem[] t = this.OrderBy(IDrawableItem => IDrawableItem.DrawOrder).ToArray();
                this.Clear();
                this.AddRange(t);
                dirtyFlag = false;
            }

            foreach (IDrawableItem node in this)
            {
                node.Draw(gameTime, spriteBatch);
            }
        }
    }
}
